package libs

import (
	"bytes"
	"encoding/binary"
	"errors"
	//"fmt"
	"github.com/golang/protobuf/proto"
	protos "im/pb"
	"net"
)

func encode(s []byte) ([]byte, error) {
	length := len(s)
	newArr := make([]byte, length)
	//bin_buf := bytes.NewBuffer(newArr)
	bin_buf := new(bytes.Buffer)
	err := binary.Write(bin_buf, binary.BigEndian, int32(length))
	//fmt.Printf("encode %v  length %v error %v\n",bin_buf.Bytes(),int32(length), err)
	if err == nil {
		copy(newArr, bin_buf.Bytes())
		copy(newArr[4:], s)
	}
	return newArr, err
}

func EncodeReq(req *protos.Request) ([]byte, error) {
	bindata, err := proto.Marshal(req)
	if err != nil {
		return nil, err
	}
	return encode(bindata)
}

func EncodeRsp(req *protos.Response) ([]byte, error) {
	bindata, err := proto.Marshal(req)
	if err != nil {
		return nil, err
	}
	return encode(bindata)
}

func DecodeReq(req []byte) (*protos.Request, error) {
	ret := &protos.Request{}
	err := proto.Unmarshal(req, ret)
	if err != nil {
		return nil, err
	}

	return ret, nil
}

func DecodeRsp(req []byte) (*protos.Response, error) {
	ret := &protos.Response{}
	err := proto.Unmarshal(req,ret)
	if err != nil {
		return nil, err
	}
	return ret,nil
}

func GetMsgLength(s []byte) int32 {
	bin_buf := bytes.NewBuffer(s[0:4])
	//fmt.Printf("leng %v\n",s[0:4])
	var x int32
	binary.Read(bin_buf, binary.BigEndian, &x)
	return x
}


func ReadReq(conn net.Conn)(*protos.Request, error){
	length := make([]byte, 4)
	_, err := conn.Read(length)
	if err != nil {
		return nil,err
	}
	l := GetMsgLength(length)
	if l==0{
		return nil,errors.New("msg length zero")
	}
	msg := make([]byte, l)
	_, err = conn.Read(msg)
	if err != nil {
		return nil,err
	}
	return DecodeReq(msg)
}
func ReadRsp(conn net.Conn) (*protos.Response, error){
	length := make([]byte, 4)
	_, err := conn.Read(length)
	//fmt.Printf("read %v ,len:%v\n",n,length)
	if err != nil {
		return nil,err
	}
	l := GetMsgLength(length)
	if l==0{
		return nil,errors.New("msg length zero")
	}
	msg := make([]byte, l)
	_, err = conn.Read(msg)
	if err != nil {
		return nil,err
	}
	//fmt.Printf("read msg:%v\n",msg)
	return DecodeRsp(msg)
}
